package cn.iocoder.yudao.module.crossborder.platform.service.provider.amazon;

import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.crossborder.platform.controller.admin.platformauth.vo.PlatformAuthSaveReqVO;
import cn.iocoder.yudao.module.crossborder.platform.dal.dataobject.platformauth.PlatformAuthDO;
import cn.iocoder.yudao.module.crossborder.platform.dal.dataobject.platformconfig.PlatformConfigDO;
import cn.iocoder.yudao.module.crossborder.platform.dal.dataobject.platformstore.PlatformStoreDO;
import cn.iocoder.yudao.module.crossborder.platform.service.platformauth.PlatformAuthService;
import cn.iocoder.yudao.module.crossborder.platform.service.platformconfig.PlatformConfigService;
import cn.iocoder.yudao.module.crossborder.platform.service.platformstore.PlatformStoreService;
import cn.iocoder.yudao.module.crossborder.platform.service.provider.amazon.client.AmazonApiClient;
import cn.iocoder.yudao.module.crossborder.platform.service.provider.base.BaseAuthProvider;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Amazon授权提供商实现
 *
 * @author 芋道源码
 */
@Component
@Slf4j
public class AmazonAuthProvider extends BaseAuthProvider {

    @Resource
    private PlatformAuthService platformAuthService;

    @Resource
    private PlatformConfigService platformConfigService;

    @Resource
    private PlatformStoreService platformStoreService;

    @Resource
    private AmazonApiClient amazonApiClient;

    private final ObjectMapper objectMapper = new ObjectMapper();

    // Amazon授权相关常量
    private static final String AMAZON_AUTH_URL = "https://sellercentral.amazon.com/apps/authorize/consent";
    private static final String AMAZON_TOKEN_URL = "https://api.amazon.com/auth/o2/token";
    private static final String AMAZON_PROFILE_URL = "https://api.amazon.com/user/profile";

    // 配置参数
    @Value("${amazon.auth.client-id:}")
    private String defaultClientId;

    @Value("${amazon.auth.client-secret:}")
    private String defaultClientSecret;

    @Value("${amazon.auth.redirect-uri:}")
    private String defaultRedirectUri;

    @Override
    public String getAuthUrl(Long storeId, String redirectUri) {
        log.info("生成Amazon授权URL: storeId={}, redirectUri={}", storeId, redirectUri);

        try {
            // 1. 获取店铺信息
            PlatformStoreDO store = platformStoreService.getPlatformStore(storeId);
            if (store == null) {
                throw new RuntimeException("店铺不存在: " + storeId);
            }

            // 2. 获取平台配置
            PlatformConfigDO platformConfig = platformConfigService.getPlatformConfigByCode("amazon");
            if (platformConfig == null) {
                throw new RuntimeException("Amazon平台配置不存在");
            }

            // 3. 获取授权配置
            Map<String, Object> authConfig = parseAuthConfig(platformConfig.getAuthConfig());
            String clientId = getConfigValue(authConfig, "clientId", defaultClientId);

            if (clientId == null || clientId.trim().isEmpty()) {
                throw new RuntimeException("Amazon客户端ID未配置");
            }

            // 4. 构建授权参数
            Map<String, String> params = new HashMap<>();
            params.put("client_id", clientId);
            params.put("scope", "sellingpartnerapi::notifications");
            params.put("response_type", "code");
            params.put("redirect_uri", redirectUri != null ? redirectUri : defaultRedirectUri);
            params.put("state", generateState(storeId)); // 防CSRF攻击

            // 5. 构建授权URL
            StringBuilder authUrl = new StringBuilder(AMAZON_AUTH_URL);
            authUrl.append("?");

            boolean first = true;
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (!first) {
                    authUrl.append("&");
                }
                authUrl.append(entry.getKey())
                       .append("=")
                       .append(URLEncoder.encode(entry.getValue(), String.valueOf(StandardCharsets.UTF_8)));
                first = false;
            }

            String finalUrl = authUrl.toString();
            log.info("生成Amazon授权URL成功: storeId={}, url={}", storeId, finalUrl);
            return finalUrl;

        } catch (Exception e) {
            log.error("生成Amazon授权URL失败: storeId={}", storeId, e);
            throw new RuntimeException("生成授权URL失败: " + e.getMessage(), e);
        }
    }

    @Override
    public boolean handleAuthCallback(Long storeId, String authCode) {
        log.info("处理Amazon授权回调: storeId={}, authCode={}", storeId, authCode);

        try {
            // 1. 获取平台配置
            PlatformConfigDO platformConfig = platformConfigService.getPlatformConfigByCode("amazon");
            if (platformConfig == null) {
                log.error("Amazon平台配置不存在");
                return false;
            }

            Map<String, Object> authConfig = parseAuthConfig(platformConfig.getAuthConfig());
            String clientId = getConfigValue(authConfig, "clientId", defaultClientId);
            String clientSecret = getConfigValue(authConfig, "clientSecret", defaultClientSecret);

            // 2. 使用授权码获取访问令牌
            Map<String, Object> tokenResponse = exchangeCodeForToken(authCode, clientId, clientSecret);
            if (tokenResponse == null || !(Boolean) tokenResponse.get("success")) {
                log.error("获取访问令牌失败: {}", tokenResponse);
                return false;
            }

            @SuppressWarnings("unchecked")
            Map<String, Object> tokenData = (Map<String, Object>) tokenResponse.get("data");
            String accessToken = (String) tokenData.get("access_token");
            String refreshToken = (String) tokenData.get("refresh_token");
            Integer expiresIn = (Integer) tokenData.get("expires_in");
            String tokenType = (String) tokenData.get("token_type");
            String scope = (String) tokenData.get("scope");

            // 3. 计算过期时间
            LocalDateTime expireTime = LocalDateTime.now().plusSeconds(expiresIn != null ? expiresIn : 3600);

            // 4. 获取或创建授权记录
            PlatformAuthDO auth = platformAuthService.getPlatformAuthByStoreId(storeId);
            if (auth == null) {
                // 创建新的授权记录
                PlatformAuthSaveReqVO createReqVO = new PlatformAuthSaveReqVO();
                createReqVO.setPlatformId(platformConfig.getId());
                createReqVO.setStoreId(storeId);
                createReqVO.setAuthType(1); // OAuth2
                createReqVO.setClientId(clientId);
                createReqVO.setClientSecret(clientSecret);
                createReqVO.setAccessToken(accessToken);
                createReqVO.setRefreshToken(refreshToken);
                createReqVO.setTokenType(tokenType);
                createReqVO.setScope(scope);
                createReqVO.setExpiresIn(expiresIn);
                createReqVO.setTokenExpireTime(expireTime);
                createReqVO.setAuthStatus(1); // 已授权
                createReqVO.setAuthTime(LocalDateTime.now());
                createReqVO.setAutoRefresh(true);

                platformAuthService.createPlatformAuth(createReqVO);
                log.info("创建Amazon授权记录成功: storeId={}", storeId);
            } else {
                // 更新现有授权记录
                platformAuthService.updateTokens(storeId, accessToken, refreshToken, expireTime);
                log.info("更新Amazon授权记录成功: storeId={}", storeId);
            }

            return true;
        } catch (Exception e) {
            log.error("处理Amazon授权回调失败: storeId={}", storeId, e);
            return false;
        }
    }

    @Override
    public boolean refreshAccessToken(Long storeId) {
        log.info("刷新Amazon访问令牌: storeId={}", storeId);

        try {
            // 1. 获取现有授权信息
            PlatformAuthDO auth = platformAuthService.getPlatformAuthByStoreId(storeId);
            if (auth == null || auth.getRefreshToken() == null) {
                log.warn("店铺授权信息不存在或无刷新令牌: storeId={}", storeId);
                return false;
            }

            // 2. 调用Amazon API刷新访问令牌
            Map<String, Object> refreshResponse = refreshToken(auth.getRefreshToken(),
                auth.getClientId(), auth.getClientSecret());

            if (refreshResponse == null || !(Boolean) refreshResponse.get("success")) {
                log.error("刷新访问令牌失败: {}", refreshResponse);
                return false;
            }

            @SuppressWarnings("unchecked")
            Map<String, Object> tokenData = (Map<String, Object>) refreshResponse.get("data");
            String newAccessToken = (String) tokenData.get("access_token");
            String newRefreshToken = (String) tokenData.getOrDefault("refresh_token", auth.getRefreshToken());
            Integer expiresIn = (Integer) tokenData.get("expires_in");

            // 3. 计算新的过期时间
            LocalDateTime newExpireTime = LocalDateTime.now().plusSeconds(expiresIn != null ? expiresIn : 3600);

            // 4. 更新授权信息
            platformAuthService.updateTokens(storeId, newAccessToken, newRefreshToken, newExpireTime);

            log.info("刷新Amazon访问令牌成功: storeId={}", storeId);
            return true;
        } catch (Exception e) {
            log.error("刷新Amazon访问令牌失败: storeId={}", storeId, e);
            return false;
        }
    }

    @Override
    public boolean validateAuth(Long storeId) {
        log.debug("验证Amazon授权状态: storeId={}", storeId);

        try {
            // 1. 获取授权信息
            PlatformAuthDO auth = platformAuthService.getPlatformAuthByStoreId(storeId);
            if (auth == null) {
                log.warn("店铺授权信息不存在: storeId={}", storeId);
                return false;
            }

            // 2. 检查授权状态
            if (auth.getAuthStatus() != 1) {
                log.warn("店铺授权状态异常: storeId={}, authStatus={}", storeId, auth.getAuthStatus());
                return false;
            }

            // 3. 检查访问令牌是否存在
            if (auth.getAccessToken() == null || auth.getAccessToken().trim().isEmpty()) {
                log.warn("访问令牌不存在: storeId={}", storeId);
                return false;
            }

            // 4. 检查令牌是否过期
            if (auth.getTokenExpireTime() != null && auth.getTokenExpireTime().isBefore(LocalDateTime.now())) {
                log.warn("访问令牌已过期: storeId={}, expireTime={}", storeId, auth.getTokenExpireTime());

                // 尝试自动刷新令牌
                if (auth.getAutoRefresh() && auth.getRefreshToken() != null) {
                    log.info("尝试自动刷新过期令牌: storeId={}", storeId);
                    return refreshAccessToken(storeId);
                }
                return false;
            }

            // 5. 调用Amazon API验证令牌有效性
            try {
                Map<String, Object> profileResponse = amazonApiClient.get("/user/profile", null, auth.getAccessToken());
                if (profileResponse != null && (Boolean) profileResponse.get("success")) {
                    log.debug("Amazon令牌验证成功: storeId={}", storeId);
                    return true;
                } else {
                    log.warn("Amazon令牌验证失败: storeId={}, response={}", storeId, profileResponse);
                    return false;
                }
            } catch (Exception e) {
                log.warn("Amazon令牌验证异常: storeId={}, error={}", storeId, e.getMessage());
                return false;
            }

        } catch (Exception e) {
            log.error("验证Amazon授权状态失败: storeId={}", storeId, e);
            return false;
        }
    }

    @Override
    public boolean revokeAuth(Long storeId) {
        log.info("撤销Amazon授权: storeId={}", storeId);

        try {
            // 1. 获取授权信息
            PlatformAuthDO auth = platformAuthService.getPlatformAuthByStoreId(storeId);
            if (auth == null) {
                log.warn("店铺授权信息不存在: storeId={}", storeId);
                return false;
            }

            // 2. 调用Amazon API撤销授权
            try {
                Map<String, String> revokeParams = new HashMap<>();
                revokeParams.put("token", auth.getAccessToken());
                revokeParams.put("token_type_hint", "access_token");

                Map<String, Object> revokeResponse = amazonApiClient.post("/auth/o2/revoke",
                    revokeParams, null, auth.getAccessToken());

                if (revokeResponse == null || !(Boolean) revokeResponse.get("success")) {
                    log.warn("调用Amazon撤销API失败: {}", revokeResponse);
                }
            } catch (Exception e) {
                log.warn("调用Amazon撤销API异常: {}", e.getMessage());
            }

            // 3. 更新本地授权状态为已撤销
            platformAuthService.updateAuthStatus(storeId, 3); // 3-已撤销

            log.info("撤销Amazon授权成功: storeId={}", storeId);
            return true;
        } catch (Exception e) {
            log.error("撤销Amazon授权失败: storeId={}", storeId, e);
            return false;
        }
    }

    // ==================== 辅助方法 ====================

    /**
     * 解析授权配置JSON
     */
    private Map<String, Object> parseAuthConfig(String authConfigJson) {
        if (authConfigJson == null || authConfigJson.trim().isEmpty()) {
            return new HashMap<>();
        }

        try {
            return objectMapper.readValue(authConfigJson, new TypeReference<Map<String, Object>>() {});
        } catch (Exception e) {
            log.warn("解析授权配置失败: {}", e.getMessage());
            return new HashMap<>();
        }
    }

    /**
     * 获取配置值
     */
    private String getConfigValue(Map<String, Object> config, String key, String defaultValue) {
        Object value = config.get(key);
        if (value instanceof String) {
            return (String) value;
        }
        return defaultValue;
    }

    /**
     * 生成状态码（防CSRF）
     */
    private String generateState(Long storeId) {
        return "store_" + storeId + "_" + UUID.randomUUID().toString().substring(0, 8);
    }

    /**
     * 使用授权码换取访问令牌
     */
    private Map<String, Object> exchangeCodeForToken(String authCode, String clientId, String clientSecret) {
        try {
            Map<String, Object> tokenRequest = new HashMap<>();
            tokenRequest.put("grant_type", "authorization_code");
            tokenRequest.put("code", authCode);
            tokenRequest.put("client_id", clientId);
            tokenRequest.put("client_secret", clientSecret);

            // 调用Amazon令牌端点
            return amazonApiClient.post(AMAZON_TOKEN_URL, tokenRequest, null, null);

        } catch (Exception e) {
            log.error("换取访问令牌失败", e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("error", e.getMessage());
            return errorResult;
        }
    }

    /**
     * 刷新访问令牌
     */
    private Map<String, Object> refreshToken(String refreshToken, String clientId, String clientSecret) {
        try {
            Map<String, Object> refreshRequest = new HashMap<>();
            refreshRequest.put("grant_type", "refresh_token");
            refreshRequest.put("refresh_token", refreshToken);
            refreshRequest.put("client_id", clientId);
            refreshRequest.put("client_secret", clientSecret);

            // 调用Amazon令牌端点
            return amazonApiClient.post(AMAZON_TOKEN_URL, refreshRequest, null, null);

        } catch (Exception e) {
            log.error("刷新访问令牌失败", e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("error", e.getMessage());
            return errorResult;
        }
    }

}
